package test.misoneism.fire.map
{
	import com.google.maps.LatLng;
	import com.google.maps.interfaces.IClientGeocoder;
	import com.google.maps.services.GeocodingEvent;
	import com.google.maps.services.GeocodingResponse;
	import com.google.maps.services.Placemark;
	import com.misoneism.fire.database.tuples.Geocode;
	import com.misoneism.fire.map.DatabaseGeocoder;
	
	import flexunit.framework.TestCase;
	import flexunit.framework.TestSuite;
	
	import test.google.maps.services.MockClientGeocoder;
	import test.misoneism.fire.database.dao.MockGeocodeDAO;
	
	public class TestDatabaseGeocoder
			extends TestCase
	{
		private static const TEST_ADDRESS:String = "test address";
		private static const TEST_LATITUDE:Number = 12.4;
		private static const TEST_LONGITUDE:Number = -67.6;
		private static const TEST_ID:int = 4;
		
		public static function suite():TestSuite
		{
			return new TestSuite(TestDatabaseGeocoder);
		}
		
		public function TestDatabaseGeocoder()
		{
			
		}
		
		override public function setUp():void
		{
			
		}
		
		override public function tearDown():void
		{
			
		}
		
		/**
		 * Test requesting a geocode on a cached entry.
		 */
		public function testExistingGeocodeEntry():void
		{
			// Setup the mock ClientGeocoder
			var clientGeocoder:MockClientGeocoder = new MockClientGeocoder();
			
			clientGeocoder.mock.method('geocode').never;
			
			// Setup the mock GeocodeDAO
			var geocodeDao:MockGeocodeDAO = new MockGeocodeDAO();
			
			var geocode:Geocode = new Geocode();
			geocode.address = TEST_ADDRESS;
			geocode.latitude = TEST_LATITUDE;
			geocode.longitude = TEST_LONGITUDE;
			geocode.id = TEST_ID;
			
			geocodeDao.mock.method('getGeocode').once.withArgs(TEST_ADDRESS).andReturn(geocode);
			geocodeDao.mock.method('insertGeocode').never;
			
			// Construct the test
			var databaseGeocoder:IClientGeocoder = new DatabaseGeocoder(clientGeocoder, geocodeDao);
			
			databaseGeocoder.addEventListener(GeocodingEvent.GEOCODING_SUCCESS, function(event:GeocodingEvent):void
				{
					assertEquals("Request type wrong.", event.request, DatabaseGeocoder.DATABASE_GEOCODE_REQUEST);
					assertEquals("Returned address does not match.", event.name, TEST_ADDRESS);
				});
			
			databaseGeocoder.geocode(TEST_ADDRESS);
			
			// Check that things were call as expected
			geocodeDao.mock.verify();
			clientGeocoder.mock.verify();
		}
		
		/**
		 * Test requesting a geocode on an uncached entry.
		 */
		public function testLoadingGeocodeEntry():void
		{
			// Setup the mock ClientGeocoder
			var clientGeocoder:MockClientGeocoder = new MockClientGeocoder();
			
			clientGeocoder.mock.method('geocode').once.withArgs(TEST_ADDRESS).andCall(function():void
			{
				var placemark:Placemark = new Placemark();
				placemark.address = TEST_ADDRESS;
				placemark.point = new LatLng(TEST_LATITUDE, TEST_LONGITUDE);
				
				var geocodingResponse:GeocodingResponse = new GeocodingResponse();
				geocodingResponse.name = TEST_ADDRESS;
				geocodingResponse.placemarks = [placemark];
				
				var event:GeocodingEvent = new GeocodingEvent(GeocodingEvent.GEOCODING_SUCCESS);
				event.name = TEST_ADDRESS;
				event.request = "geocode";
				event.response = geocodingResponse;
				
				clientGeocoder.dispatchEvent(event);
			});
			
			// Setup the mock GeocodeDAO
			var geocodeDao:MockGeocodeDAO = new MockGeocodeDAO();
			
			geocodeDao.mock.method('getGeocode').once.withArgs(TEST_ADDRESS).returns(null);
			geocodeDao.mock.method('insertGeocode').once.withArgs(TEST_ADDRESS, TEST_LATITUDE, TEST_LONGITUDE).returns(TEST_ID);
			
			// Construct the test
			var databaseGeocoder:IClientGeocoder = new DatabaseGeocoder(clientGeocoder, geocodeDao);
			
			databaseGeocoder.geocode(TEST_ADDRESS);
			
			// Check that things were call as expected
			geocodeDao.mock.verify();
			clientGeocoder.mock.verify();
		}
	}
}